iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 17
0
Modern Web

實作小範例入門 Vue & Vuex 2.0系列 第 17

vue & vuex 17 - 覺得 store 有點亂,動手拆成 modules 吧!

  • 分享至 

  • xImage
  •  

今天目標:

  • 自己的 store 自己整理。

目前我們所用的方法是所有 action 程式放在 actions.js 裡面。

mutations, getters 以此類推..。

所以檔案中包含著 count 與 todo 的程式,辨識的方法可能是加個註解。

如果未來功能多的時後,會不會有點難維護呢?(程式越長越長)

因此今天的目標就是利用 vuex modules 方法,來整理我們的程式。


資料結構:

官方提供這樣的結構參考:

└── store
    ├── index.js      // root 組合 modules 的地方
    ├── actions.js    // root 最外層的 action
    ├── mutations.js  // root 最外層的 mutation
    └── modules
        ├── count.js  // Count modules
        └── todo.js   // Todo modules

你也利用這樣的結構:

└── store
    ├── index.js           // root 組合所有 modules 的地方
    ├── actions.js         // root 最外層的 action 
    ├── mutations.js       // root 最外層的 mutation 可以改變所有模組的 state
    ├── getter.js          // root 最外層的 getter 可以拿到所有模組的 state
    ├── mutations_types.js // 所有 mutation key 存放的地方
    ├── count
    │   ├── index.js      // 組合 count 與 export todo 的地方
    │   ├── actions.js    // count action
    │   └── mutations.js  // count state, mutation
    ├── todo
    │   ├── index.js      // 組合 todo 與 export todo 的地方
    │   ├── actions.js    // todo action
    │   └── mutations.js  // todo state, mutation

如果用資料夾整理的方式
記得 vuex 預設會去找 index.js 因此這是最好的組裝場所。

端看團隊的選擇,與 state 的大小,可能 API 超過五隻我們就會選擇第二種方式去開發。

檔名跟結構其實官方沒有規定我們要怎麼放,只要不違反 vuex 的原則

  1. 只有 mutation 可以改變 state。
  2. 非同步的事件應該在 action 處理。
  3. mutation 只能處理同步事件。

由於我們程式碼不多,所以就利用官方提供的方法來動手來整理 count 與 todo 吧!

以下只紀錄 count 的部分。


modules/count.js

/* 
  這邊可以改為用 types 物件取代 matutions_type.js (繼續用也可以)
  然後在前面加上模組名稱作為前綴,用來避免與其他模組重複。
  因為 action、mutation、和 getter 依然是註冊在全域的命名空間
*/
const types = {
  INCREASE: 'count/INCREASE',
  DECREASE: 'count/DECREASE',
  COUNT_RESET: 'count/COUNT_RESET'
}

// count state 必須是 Object
const state = {
  count: 0
}

// getters 也可以整理到這邊直接返回 count 內容
const getters = {
  getCount: state => state.count
}

// actions 也是以 Object 形式建構。
const actions = {
  actionIncrease ({ commit }, num) {
    commit(types.INCREASE, num);
  },
  actionDecrease ({ commit }, num) {
    commit(types.DECREASE, num);
  },
  actionCountReset ({ commit }) {
    commit(types.COUNT_RESET);
  }
}

// mutations
const mutations = {
  [types.INCREASE] (state, num) {
    state.count += num;
    console.log('newINCREASE', num, 'state?', state.count);
  },
  [types.DECREASE] (state, num) {
    state.count -= num;
    console.log('newDECREASE', num, 'state?', state.count);
  },
  [types.COUNT_RESET] (state) {
    state.count = 0;
    console.log('newCOUNT_RESET - state?', state.count);
  }
}

/*
  因為我們把 vuex 所有職權都寫在同一隻檔案,
  所以必須要 export 出去給最外層 index.js 組合使用
*/
export default {
  state,
  getters,
  actions,
  mutations
}

types

index.js (root)

import Vue from 'vue';
import Vuex from 'vuex';
// root
import * as getters from './getters.js';
// modules
import count from './modules/count';
import todo from './modules/todo';

Vue.use( Vuex );

export default new Vuex.Store({
  // root
  getters,
  // 將整理好的 modules 放到 vuex 中組合
  modules: {
    count,
    todo
  },
  // 嚴格模式,禁止直接修改 state
  strict: true
});

整理成 modules 與原本寫在 root 有什麼不同?


寫在 root 中的 store:

state: {
  count: 0,
  todo: [ .. ]
}

整理成 modules 的 store:

state: {
  count: {
    count: 0
  }
  todo: {
    todo: [ .. ]
  }
}

多包了一層!為什麼?


我們在 index.js (root) 是怎麼組合的?

import count from './modules/count';

export default new Vuex.Store({
  modules: {
    count: count
// modules name: value
  }
});

那 modules/count 是怎麼組合的呢?

const state = {
  count: 0
}

因此最後的組合就會變成這樣囉:

state: {
  count: {
    count: 0
  }
}

整理成 modules 的好處是:

相關 state 自成一國,假這我有 user 有關的狀態操作,可以全部寫在一起。

我在 gettermutations 操作的時候,就不需要一層一層的去找我的 state

從 root 的話我們可以能要return state.user.user.username

包裝 modules 我只要針對 return state.user.username 去操作就可以了。

不管是命名,或是操作 state 都會變得更扁平,更直覺。

那要怎麼拿到其他 modules 的 state

如果要取得或改變其他 modules 的狀態,你必須將程式設計在 root 那層。如 gettermutations

getter.js

// get count & todo
export const getCountandTodo = state => {
  return {
    count: state.count.count,
    todo: state.todo.todos,
  }
}

// just return all state
export const getAllstate = state => state

取得 state 示意圖:

vuex state & modules state

命名空間

不管是在 root 或是 modules 所有 action、mutation、和 getter 依然是註冊在全域的命名空間,因為 store 只有一個。


github 完整範例:

實作小範例入門 Vue & Vuex 2.0 - github 完整範例

使用 git checkout 切換每天範例。


上一篇
vue & vuex 16 - 自訂按鈕 custom checkbox ($emit, $on)
下一篇
vue & vuex 18 - 開發小技巧
系列文
實作小範例入門 Vue & Vuex 2.030
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言